package rediscache

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	"gitee.com/korbenzhang/gox/xcache"
	"gitee.com/korbenzhang/gox/xconfig"
	"github.com/go-redis/redis/v8"
)

// Create Conf.
type Conf struct {
	Host     string `yaml:"Host"`
	Port     int    `yaml:"Port"`
	Password string `yaml:"Password"`
	DB       int    `yaml:"DB"`
}

// GetClient .
func GetClient(conf Conf) *redis.Client {
  // expand env in config
  conf.Host = os.ExpandEnv(conf.Host)
  conf.Password = os.ExpandEnv(conf.Password)

	addr := fmt.Sprintf("%s:%d", conf.Host, conf.Port)
	client := redis.NewClient(&redis.Options{
		Addr:     addr,
		Password: conf.Password,
		DB:       conf.DB,
	})
	return client
}

// RedisCache
type RedisCache struct {
	Client *redis.Client
}

// make sure implemetns interface
var _ xcache.Cache = &RedisCache{}

// NewCache create new caceh instanse.
func NewCache(conf Conf) *RedisCache {
	return &RedisCache{
		Client: GetClient(conf),
	}
}

// NewConfigCache .
func NewConfigCache(conf xconfig.Config) *RedisCache {
	var c Conf
	if err := conf.Unmarshal("Redis", &c); err != nil {
		log.Println("rediscache: config redis error: ", err)
	}
	return NewCache(c)
}

// Set .
func (s *RedisCache) Set(key string, value any, expires time.Duration) error {
	return s.Client.Set(context.TODO(), key, value, expires).Err()
}

// Put .
func (s *RedisCache) Put(key string, value any) error {
	return s.Set(key, value, 0)
}

// GetBytes .
func (s *RedisCache) GetBytes(key string) ([]byte, error) {
	return s.Client.Get(context.TODO(), key).Bytes()
}

// Get .
func (s *RedisCache) GetString(key string) (string, error) {
  return s.Client.Get(context.TODO(), key).Result()
}

// Del .
func (s *RedisCache) Del(key string) error {
	return s.Client.Del(context.TODO(), key).Err()
}

// Ping
func (s *RedisCache) Ping() error {
	return s.Client.Ping(context.TODO()).Err()
}
